﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls.DataVisualization.Charting;
using System.Windows.Threading;
using BehaviorModel;
using QSDesigner.Windows.Interfaces;

namespace QSDesigner.Windows
{
    /// <summary>
    /// Interaction logic for RejectProbabilityHistogramDataWindow.xaml
    /// </summary>
    public partial class RejectProbabilityHistogramDataWindow : Window, IRejectProbabilityHistogramDataWindow, IUpdatableWindow
    {
        private const double EPS = 0.1;

        private readonly int _lastStatIndex;

        private double Min { get; set; }
        private double Max { get; set; }

        public DispatcherTimer DispatcherTimer { get; set; }

        public RejectProbabilityHistogramDataWindow()
        {
            InitializeComponent();

            convergence.Text = String.Format("{0:F8}", 0);

            DispatcherTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(1000) };
            DispatcherTimer.Tick += (s, a) =>
            {
                Action action = UpdateChart;
                Dispatcher.Invoke(action);
            };

            Min = 1;
            Max = 0;
            _lastStatIndex = StatisticController.GetInstance().Statistic.RejectProbabilityHistogramData.Count - 1;
        }

        public void UpdateChart()
        {
            StatisticController.GetInstance().Statistic.UpdateRejectProbabilityHistogramData();

            var stat = StatisticController.GetInstance().Statistic.RejectProbabilityHistogramData;

            var newMax = stat.Values.Max();
            var newMin = stat.Values.Min();

            var conv = newMax - newMin;

            convergence.Text = String.Format("{0:F8}", conv);

            Max = Math.Max(Max, newMax);
            Min = Math.Min(Min, newMin);

            ((LinearAxis)((LineSeries)(lineChart.Series[0])).DependentRangeAxis).Maximum = Max * (1 + EPS * conv);
            ((LinearAxis)((LineSeries)(lineChart.Series[0])).DependentRangeAxis).Minimum = Min * (1 - EPS * conv);

            //Statistics
            ((LineSeries)lineChart.Series[0]).ItemsSource = null;
            ((LineSeries)lineChart.Series[0]).ItemsSource = stat;

            //Upper bound
            ((LineSeries)lineChart.Series[1]).ItemsSource = GetYBound(newMax);

            //Lower bound
            ((LineSeries)lineChart.Series[2]).ItemsSource = GetYBound(newMin);
        }

        private Dictionary<int, double> GetYBound(double boundY)
        {
            return new Dictionary<int, double> { { 0, boundY }, { _lastStatIndex, boundY } };
        }

        public void StartFetchData()
        {
            // Start the timer
            DispatcherTimer.Start();
        }

        public void StopFetchData()
        {
            DispatcherTimer.Stop();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            UpdateYBounds();
        }

        private void UpdateYBounds()
        {
            var stat = StatisticController.GetInstance().Statistic.RejectProbabilityHistogramData;
            Max = stat.Values.Max();
            Min = stat.Values.Min();
        }
    }
}
